﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Crosland.Offline.Core;
using Crosland.Offline.Logic;
using Crosland.Offline.WinForm.Properties;
using Crosland.Util;
using Crosland.Framework.Base;

namespace Crosland.Offline.WinForm
{
    public partial class RolEdit : Form
    {
        public RolEdit()
        {            
        }

        public RolEdit(RolList formList)
        {
            InitializeComponent();
            this.CargarDatos();
            this.formList = formList;
        }

        public RolList formList;

        public event EventHandler GrabarCompleto;

        /// <summary>
        /// Instancia de Clase que maneja la logica
        /// </summary>
        SeguridadLogic logic = new SeguridadLogic();

        private System.String mensaje;

        private System.Boolean indEdicion;

        /// <summary>
        /// Indicacion si es edicion o registro
        /// </summary>
        public System.Boolean IndEdicion
        {
            get { return indEdicion; }
            set { indEdicion = value; }
        }

        /// <summary>
        /// Permite establecer el código del registro
        /// </summary>
        public System.String CodigoRegistro
        {
            get { return this.txtCodigo.Text; }
            set { this.txtCodigo.Text = value; }
        }
        
        List<Opcion> treeItems;
        List<Opcion> treeItemsChild;


        /// <summary>
        /// Permite realizar búsquedas
        /// </summary>
        protected void CargarDatos()
        {       
            this.ddlEstado.DataSource = HelperClass.ListarEstados();
            this.ddlEstado.DisplayMember = Resources.CampoNombre;
            this.ddlEstado.ValueMember = Resources.CampoID;                      
        }

        /// <summary>
        /// Inicializa los datos de la pantalla
        /// </summary>
        public void Inicializar()
        {
            this.CargarArbol(new List<int>());
        }
        
        /// <summary>
        /// Carga los opciones del sistema en el arbol
        /// </summary>
        protected void CargarArbol(List<int> list)
        {
            this.tvOpciones.Nodes.Clear();
            treeItems = this.logic.ListarOpciones();
            if (treeItems.Count > 0)
            {
                this.LlenarOpciones(null, null, this.tvOpciones, list);
            }

            this.tvOpciones.ExpandAll();
        }

        /// <summary>
        /// Carga en el treview, las opciones del sistema
        /// </summary>
        /// <param name="codigoPadre"></param>
        /// <param name="node"></param>
        /// <param name="tree"></param>
        public void LlenarOpciones(int? codigoPadre, TreeNode node, TreeView tree, List<int> list)
        {
            treeItemsChild = treeItems.FindAll(delegate(Opcion item) { return (item.IdPadre == codigoPadre); });

            foreach (Opcion hijos in treeItemsChild)
            {
                TreeNode newNode = new TreeNode(hijos.DesNombre);
                newNode.Tag = hijos.ID;

                if (list.Contains(hijos.ID))
                {
                    newNode.Checked = true;
                }

                if (codigoPadre == null) tree.Nodes.Add(newNode);
                else node.Nodes.Add(newNode);
                this.LlenarOpciones(hijos.ID, newNode, null, list);
            }
        }       

        /// <summary>
        /// Permite seleccionar los nodos padres como obligatorio
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tvOpciones_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.Checked)
            {
                this.MarcarPadres(e.Node);
                this.MarcarHijos(e.Node, true);
            }
            else 
            {
                this.DesmarcarPadres(e.Node);
                this.MarcarHijos(e.Node, false);
            }
        }

        /// <summary>
        /// Marca los padres del item seleccionado
        /// </summary>
        /// <param name="node"></param>
        public void MarcarPadres(TreeNode node)
        {
            TreeNode nodo = node.Parent;     

            if (nodo != null)
            {
                node.Checked = true;
                this.MarcarPadres(nodo);
            }
            else
            {
                node.Checked = true;
            }
        }

        /// <summary>
        /// Desmarca los padres en caso de no haber seleccion
        /// </summary>
        /// <param name="node"></param>
        public void DesmarcarPadres(TreeNode node)
        {
            TreeNode nodo = node.Parent;

            if (nodo != null)
            {
                bool flag = true;
                foreach (TreeNode item in nodo.Nodes)
                {
                    if (item.Checked) flag = false;
                }
                if (flag)
                {
                    nodo.Checked = false;
                    this.DesmarcarPadres(nodo);
                }
            }          
        }

        /// <summary>
        /// Permite marcar o desmarcar los nodos secundarios
        /// </summary>
        /// <param name="node"></param>
        /// <param name="flag"></param>
        public void MarcarHijos(TreeNode node, bool flag)
        {
            TreeNodeCollection nodes = node.Nodes;

            if (nodes.Count > 0)
            {
                foreach (TreeNode nodo in nodes)
                {
                    nodo.Checked = flag;
                    this.MarcarHijos(nodo, flag);
                }
            }
        }

        /// <summary>
        /// Permite editar los datos del registro
        /// </summary>
        /// <param name="id"></param>
        public void EditarRegistro(string id)
        {
            Rol entity = this.logic.ObtenerGrupo(int.Parse(id));

            this.txtNombre.Text = entity.DesNombre;
            this.txtDescripcion.Text = entity.DesDescripcion;
            this.ddlEstado.SelectedValue = entity.IndEstado;

            this.CargarArbol(this.logic.ObtenerOpcionesPorGrupo(int.Parse(id)));
        }

        /// <summary>
        /// Permite grabar los datos del registro
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGrabar_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.Grabar())
                {
                    this.formList.formEdit = this;
                    this.formList.GuardarCompleto();
                    this.Close();
                    this.GrabarCompleto(sender, e);
                }
            }
            catch
            {
                MessageBox.Show(Resources.MsgErrorGrabar);
            }
        }

        /// <summary>
        /// Permite grabar los datos del formulario
        /// </summary>
        protected bool Grabar()
        {
            if (this.Validar())
            {
                Rol entity = new Rol();
                entity.ID = (this.IndEdicion) ? int.Parse(this.txtCodigo.Text) : 0;
                entity.DesNombre = this.txtNombre.Text;
                entity.DesDescripcion = this.txtDescripcion.Text;
                entity.IndEstado = this.ddlEstado.SelectedValue.ToString();

                List<int> listOpcion = this.ObtenerNodoSeleccionados(this.tvOpciones);

                if (listOpcion.Count > 0)
                {
                    this.logic.GrabarGrupo(entity, listOpcion);
                    return true;
                }
                else
                {
                    MessageBox.Show(Resources.SeleccioneOpcion);
                    return false;
                }
            }
            else 
            {       
                MessageBox.Show(mensaje, Resources.TituloConfirmacion, MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);
                return false;           
            }           
        }

        /// <summary>
        /// Permite validar los datos del formulario
        /// </summary>
        protected bool Validar()
        {
            StringBuilder msg = new StringBuilder();
            
            msg.Append(Tools.ValidarCampo(this.txtNombre, "Nombre", true, TipoValidacion.Alfanumerico));           
            msg.Append(Tools.ValidarCampo(this.ddlEstado, "Estado", true, TipoValidacion.Ninguno));          

            if (msg.Length > 0)
            {
                mensaje = msg.ToString();
                return false;
            }

            return true;
        }

        /// <summary>
        /// Retorna los elementos seleccionados de un treeview
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="idPadre"></param>
        /// <returns></returns>
        public  List<int> ObtenerNodoSeleccionados(TreeView tv)
        {
            List<int> list = new List<int>();

            foreach (TreeNode tn in tv.Nodes)
            {
                if (tn.Checked)
                {
                    list.Add(int.Parse(tn.Tag.ToString()));
                }
                if (tn.Nodes.Count > 0)
                {
                    foreach (TreeNode cTn in tn.Nodes)
                    {
                        list.AddRange(ObtenerNodoHijoRecursivo(cTn));
                    }
                }
            }
            return list;
        }


        /// <summary>
        /// Retorna los nodos hijos seleccionados de un treeview
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="idPadre"></param>
        /// <returns></returns>
        public List<int> ObtenerNodoHijoRecursivo(TreeNode tn)
        {
            List<int> list = new List<int>();
            if (tn.Checked)
            {
                list.Add(int.Parse(tn.Tag.ToString()));
            }
            if (tn.Nodes.Count > 0)
            {
                foreach (TreeNode tnC in tn.Nodes)
                {
                    list.AddRange(ObtenerNodoHijoRecursivo(tnC));
                }
            }
            return list;
        }

        /// <summary>
        /// Permite salir de la aplicación
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSalir_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        
    }
}
